from fastapi import APIRouter, HTTPException, Depends

from backend.schemas.user import (
    UserCreate, UserOut, UserUpdate, UserPasswordChange, UserList, PaginationParams,
    RoleCreate, RoleUpdate, RoleOut, RoleList, 
    PermissionCreate, PermissionOut, PermissionList
)
from backend.services.user_service import UserService, RoleService, PermissionService
from backend.common.jwt import get_current_active_user, get_current_admin_user, require_permissions
from backend.schemas.response import ResponseBase
from backend.models.user import User
from typing import List, Optional, Dict, Union
from fastapi import File, UploadFile
import os
import uuid
import shutil   
import hashlib
import base64
from functools import lru_cache
import time

router = APIRouter()

# 头像缓存，键为路径，值为(base64编码, 缓存时间)的元组
_avatar_cache: Dict[str, tuple] = {}
# 缓存过期时间（秒）
_AVATAR_CACHE_TTL = 3600  # 1小时

# Helper function to convert avatar path to base64
def convert_avatar_to_base64(avatar_path: Optional[str]) -> Optional[str]:
    """将头像文件路径转换为base64编码字符串"""
    if not avatar_path or avatar_path.startswith('data:'):
        return avatar_path
        
    # 检查缓存
    now = time.time()
    if avatar_path in _avatar_cache:
        cached_data, timestamp = _avatar_cache[avatar_path]
        # 如果缓存未过期，直接返回
        if now - timestamp < _AVATAR_CACHE_TTL:
            return cached_data
    
    try:
        # 构建头像文件的完整路径
        full_path = os.path.join("backend", avatar_path.lstrip('/'))
        if os.path.exists(full_path):
            with open(full_path, "rb") as f:
                file_content = f.read()
                # 根据文件扩展名确定MIME类型
                file_ext = full_path.split('.')[-1].lower()
                mime_type = f"image/{file_ext}" if file_ext != 'jpg' else "image/jpeg"
                base64_data = f"data:{mime_type};base64,{base64.b64encode(file_content).decode('utf-8')}"
                
                # 更新缓存
                _avatar_cache[avatar_path] = (base64_data, now)
                
                # 清理过期缓存条目
                if len(_avatar_cache) > 100:  # 避免缓存无限增长
                    expired_keys = [k for k, (_, t) in _avatar_cache.items() if now - t > _AVATAR_CACHE_TTL]
                    for k in expired_keys:
                        _avatar_cache.pop(k, None)
                
                return base64_data
    except Exception as e:
        print(f"加载头像出错: {e}")
        
    return avatar_path

# Helper function for building UserOut from User model
async def build_user_out_from_model(user: Optional[User]) -> Optional[UserOut]:
    """从User模型构建UserOut响应对象"""
    if not user:
        return None
        
    # 将角色转换为角色DTO
    roles = []
    for role in user.roles:
        permissions = []
        for permission in role.permissions:
            permissions.append(PermissionOut(
                id=permission.id,
                name=permission.name,
                code=permission.code,
                description=permission.description,
                created_at=str(permission.created_at),
                updated_at=str(permission.updated_at)
            ))
        roles.append(RoleOut(
            id=role.id,
            name=role.name,
            code=role.code,
            description=role.description,
            permissions=permissions,
            created_at=str(role.created_at),
            updated_at=str(role.updated_at)
        ))
    
    # 如果存在头像则转换为base64
    avatar_base64 = convert_avatar_to_base64(user.avatar)
    
    # 获取部门信息
    department_id = None
    department_name = None
    department_path = None
    if user.department:
        department_id = user.department.dept_id
        department_name = user.department.dept_name
        
        # 使用ancestors字段构建完整的部门路径
        if user.department.ancestors:
            # ancestors包含OU=部门名格式
            department_path = user.department.ancestors.replace('OU=', '').replace(',', '/')
    
    return UserOut(
        id=user.id,
        username=user.username,
        name=user.name,
        email=user.email,
        avatar=avatar_base64 if avatar_base64 else user.avatar,
        phone=user.phone,
        gender=user.gender,
        bio=user.bio,
        roles=roles,
        department_id=department_id,
        department_name=department_name,
        department_path=department_path,
        status=user.status,
        created_at=str(user.created_at),
        updated_at=str(user.updated_at)
    )

@router.get("/user/me", response_model=ResponseBase[UserOut], summary="获取当前用户信息")
async def get_me(current_user: User = Depends(get_current_active_user)):
    # 获取带有角色的用户信息
    user = await UserService.get_user_by_id(current_user.id)
    if not user:
        raise HTTPException(status_code=404, detail="用户不存在")
    user_out = await build_user_out_from_model(user)
    return ResponseBase[UserOut](data=user_out)

@router.get("/user/profile", response_model=ResponseBase[UserOut], summary="获取当前用户资料")
async def get_profile(current_user: User = Depends(get_current_active_user)):
    # 获取带有角色的用户信息
    user = await UserService.get_user_by_id(current_user.id)
    if not user:
        raise HTTPException(status_code=404, detail="用户不存在")
    user_out = await build_user_out_from_model(user)
    return ResponseBase[UserOut](data=user_out)

@router.put("/user/profile", response_model=ResponseBase[UserOut], summary="更新当前用户资料")
async def update_profile(
    user_data: UserUpdate,
    current_user: User = Depends(get_current_active_user)
):
    # 允许普通用户更新名称、电子邮件、电话、性别和简介
    filtered_data = {
        "name": user_data.name,
        "email": user_data.email,
        "phone": user_data.phone,
        "gender": user_data.gender,
        "bio": user_data.bio
    }
    
    user_obj = await UserService.update_user(current_user.id, filtered_data)
    if not user_obj:
        raise HTTPException(status_code=404, detail="用户不存在")
    
    user_out = await build_user_out_from_model(user_obj)
    return ResponseBase[UserOut](data=user_out)

@router.put("/user/password", response_model=ResponseBase, summary="修改当前用户密码")
async def change_password(
    password_data: UserPasswordChange,
    current_user: User = Depends(get_current_active_user)
):
    success = await UserService.change_password(
        current_user.id, 
        password_data.old_password, 
        password_data.new_password
    )
    if not success:
        raise HTTPException(status_code=400, detail="原密码错误")
    return ResponseBase(message="密码修改成功")

@router.get("/user", response_model=ResponseBase[UserList], summary="获取用户列表")
async def get_users(
    pagination: PaginationParams = Depends(),
    department_id: Optional[str] = None,
    current_user: User = Depends(require_permissions(["user:list"]))
):
    # 如果指定了部门则按部门过滤用户
    if department_id:
        users, total = await UserService.get_users_by_department(department_id, page=pagination.page, limit=pagination.limit)
    else:
        users, total = await UserService.get_users(page=pagination.page, limit=pagination.limit)
    user_list = []
    
    for user in users:
        # 将角色转换为角色DTO
        roles = []
        for role in user.roles:
            permissions = []
            for permission in role.permissions:
                permissions.append(PermissionOut(
                    id=permission.id,
                    name=permission.name,
                    code=permission.code,
                    description=permission.description,
                    created_at=str(permission.created_at),
                    updated_at=str(permission.updated_at)
                ))
            roles.append(RoleOut(
                id=role.id,
                name=role.name,
                code=role.code,
                description=role.description,
                permissions=permissions,
                created_at=str(role.created_at),
                updated_at=str(role.updated_at)
            ))
        
        # 如果存在头像则转换为base64
        avatar_base64 = convert_avatar_to_base64(user.avatar)
        
        # 获取部门名称（如果存在）
        department_id = None
        department_name = None
        if user.department:
            try:
                # 确保部门是一个Department对象而不是QuerySet
                if hasattr(user.department, 'dept_id'):
                    department_id = user.department.dept_id
                    department_name = user.department.dept_name
                else:
                    # 如果是QuerySet，进行额外处理
                    print(f"警告: 用户 {user.id} 的部门是一个QuerySet而不是Department对象")
            except Exception as e:
                print(f"获取用户 {user.id} 的部门信息时出错: {str(e)}")
            
        user_list.append(UserOut(
            id=user.id,
            username=user.username,
            name=user.name,
            email=user.email,
            avatar=avatar_base64 if avatar_base64 else user.avatar,
            roles=roles,
            department_id=department_id,
            department_name=department_name,
            status=user.status,
            created_at=str(user.created_at),
            updated_at=str(user.updated_at)
        ))
    
    return ResponseBase[UserList](data=UserList(items=user_list, total=total))

@router.post("/user", response_model=ResponseBase[UserOut], summary="创建用户")
async def create_user(
    user: UserCreate,
    current_user: User = Depends(require_permissions(["user:create"]))
):
    exist_user = await UserService.get_user_by_username(user.username)
    if exist_user:
        raise HTTPException(status_code=400, detail="用户名已存在")
    user_obj = await UserService.create_user(
        username=user.username, 
        password=user.password,
        email=user.email,
        name=user.name,
        role_ids=user.role_ids,
        department_id=user.department_id,
        status=user.status
    )
    
    # 获取包含角色的新用户信息
    user_obj = await UserService.get_user_by_id(user_obj.id)
    if not user_obj:
        raise HTTPException(status_code=404, detail="创建用户后无法获取用户信息")
        
    user_out = await build_user_out_from_model(user_obj)
    return ResponseBase[UserOut](data=user_out)

@router.put("/user/{user_id}", response_model=ResponseBase[UserOut], summary="更新用户")
async def update_user(
    user_id: int,
    user: UserUpdate,
    current_user: User = Depends(require_permissions(["user:update"]))
):
    user_obj = await UserService.update_user(user_id, user.dict(exclude_unset=True))
    if not user_obj:
        raise HTTPException(status_code=404, detail="用户不存在")
    
    user_out = await build_user_out_from_model(user_obj)
    return ResponseBase[UserOut](data=user_out)

@router.delete("/user/{user_id}", response_model=ResponseBase, summary="删除用户")
async def delete_user(
    user_id: int,
    current_user: User = Depends(require_permissions(["user:delete"]))
):
    if current_user.id == user_id:
        raise HTTPException(status_code=400, detail="不能删除当前登录用户")
    
    success = await UserService.delete_user(user_id)
    if not success:
        raise HTTPException(status_code=404, detail="用户不存在")
    return ResponseBase(message="删除成功")

@router.put("/user/{user_id}/password", response_model=ResponseBase, summary="修改用户密码")
async def change_user_password(
    user_id: int,
    password_data: UserPasswordChange,
    current_user: User = Depends(get_current_active_user)
):
    # 检查用户是否有权限或正在修改自己的密码
    has_permission = False
    
    if current_user.id == user_id:
        has_permission = True
    else:
        user_permissions = await UserService.get_user_permissions(current_user)
        if "user:update" in user_permissions:
            has_permission = True
    
    if not has_permission:
        raise HTTPException(status_code=403, detail="没有权限执行此操作")
    
    success = await UserService.change_password(
        user_id, 
        password_data.old_password, 
        password_data.new_password
    )
    if not success:
        raise HTTPException(status_code=400, detail="原密码错误或用户不存在")
    return ResponseBase(message="密码修改成功")


@router.post("/user/avatar", response_model=ResponseBase[UserOut], summary="上传用户头像")
async def upload_avatar(
    file: UploadFile = File(...),
    current_user: User = Depends(get_current_active_user)
):
    # 验证文件类型
    if not file or not file.content_type or not file.content_type.startswith('image/'):
        raise HTTPException(status_code=400, detail="只允许上传图片文件")
    
    # 读取文件内容
    file_content = await file.read()
    
    # 使用uuid生成唯一文件名
    file_ext = 'png'
    if file.filename and '.' in file.filename:
        file_ext = file.filename.split('.')[-1]
    unique_filename = f"{uuid.uuid4()}.{file_ext}"
    
    # 定义头像目录并确保它存在
    avatar_dir = os.path.join("backend", "static", "avatars")
    os.makedirs(avatar_dir, exist_ok=True)
    
    # 保存文件到磁盘
    file_path = os.path.join(avatar_dir, unique_filename)
    with open(file_path, "wb") as f:
        f.write(file_content)
    
    # 将相对路径存储在数据库中
    db_path = f"/static/avatars/{unique_filename}"
    user_data = {"avatar": db_path}
    user_obj = await UserService.update_user(current_user.id, user_data)
    if not user_obj:
        raise HTTPException(status_code=404, detail="用户不存在")
    
    # 将保存的文件转换为base64用于响应
    avatar_base64 = convert_avatar_to_base64(db_path)
    
    user_out = await build_user_out_from_model(user_obj)
    
    # 确保avatar_base64被正确设置
    if user_out:
        user_out.avatar = avatar_base64
    
    return ResponseBase[UserOut](
        data=user_out,
        message="头像上传成功"
    )

@router.get("/user/permissions", response_model=ResponseBase[List[str]], summary="获取当前用户权限")
async def get_user_permissions(current_user: User = Depends(get_current_active_user)):
    """获取当前登录用户的所有权限代码"""
    permissions = await UserService.get_user_permissions(current_user)
    return ResponseBase[List[str]](data=list(permissions), message="获取权限成功") 